﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;

namespace Module.FlowChart.Model
{
    internal abstract class FCWorkPageBase : WorkPage
    {
        public const byte StartFlag = 110;//文件开始标志
        public const byte EndFlag = 120;//文件结束标志
        public const int DefaultNodeInitCount = 20;//初始化的节点集合容量
        public const int DefaultLineInitCount = 20;//初始化的线段集合容量


        public int NodeCount => Nodes.Count;//当前节点数量
        public int LineCount => Lines.Count;//当线段点数量
        public Dictionary<int, FCNode> Nodes;//节点集合
        public Dictionary<int, FCLine> Lines;//线段集合
        protected int NodeIdPointer;//节点Id指针
        protected int LineIdPointer;//线段Id指针

        public FCWorkPageBase()
        {
            StartNode = 1;
            IsChanged = false;
        }

        public FCWorkPageBase(string name) : base(name)
        {
            StartNode = 1;
            IsChanged = true;
            Nodes = new Dictionary<int, FCNode>(DefaultNodeInitCount);
            Lines = new Dictionary<int, FCLine>(DefaultLineInitCount);
            NodeIdPointer = LineIdPointer = 0;
        }


        #region NodeAndLine
        public virtual FCNode FindNode(int id)
        {
            if (Nodes.ContainsKey(id))
                return Nodes[id];
            throw new Exception("Cant find this node");
        }
        public virtual FCLine FindLine(int id)
        {
            if (Lines.ContainsKey(id))
                return Lines[id];
            throw new Exception("Cant find this line");
        }
        public virtual int AddNode(FCNode node)
        {
            IsChanged = true;
            node.Id = ++NodeIdPointer;
            Nodes[NodeIdPointer] = node;
            return node.Id;
        }
        public virtual int AddLine(FCLine line)
        {
            IsChanged = true;
            line.Id = ++LineIdPointer;
            Lines[LineIdPointer] = line;
            return line.Id;
        }
        /// <summary>
        /// 移除节点，返回"" 或错误信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public string RemoveNode(int id)
        {
            if (!Nodes.ContainsKey(id))
            {
                return "不能移除不存在的节点";
            }
            FCNode node = Nodes[id];
            if (node.Type == FCNodeType.Terminal)
            {
                if (node.IsStartNode)
                    return "不能删除起始节点";
                bool find = false;
                foreach (var item in Nodes.Values)
                {
                    if (item.Id != id && item.Type == FCNodeType.Terminal && !item.IsStartNode)
                    {
                        find = true;
                        break;
                    }
                }
                if (!find)
                    return "必须要有至少一个终节点";
            }

            IsChanged = true;
            Nodes.Remove(id);
            //删除与之相对应的节点
            List<int> removes = new List<int>();
            foreach (var line in Lines.Values)
            {
                if (line.From == id)
                {
                    removes.Add(line.Id);
                }
                else if (line.To == id)
                {
                    removes.Add(line.Id);
                }
            }
            foreach (var line in removes)
            {
                RemoveLine(line);
            }
            return "";
        }
        /// <summary>
        /// 移除节点相关的线段，返回"" 或错误信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public string RemoveLineOfNode(int id)
        {
            if (!Nodes.ContainsKey(id))
            {
                return "不存在的节点";
            }
            //删除与之相对应的节点
            List<int> removes = new List<int>();
            foreach (var line in Lines.Values)
                if (line.From == id || line.To == id)
                    removes.Add(line.Id);
            IsChanged = IsChanged ? true : removes.Count > 0;
            foreach (var line in removes)
                RemoveLine(line);
            return "";
        }
        public virtual string RemoveLine(int id)
        {
            IsChanged = true;
            if (!Lines.ContainsKey(id))
            {
                return ("没有这个线段");
            }
            var line = Lines[id];
            Lines.Remove(id);
            return "";
        }
        #endregion



        public override bool Save(BinaryWriter bw)
        {
            IsChanged = false;

            bw.Write(TypeName);
            //头信息
            bw.Write(StartFlag);
            bw.Write(Name);
            bw.Write(PaperSize.Width);
            bw.Write(PaperSize.Height);

            //idptr
            bw.Write(NodeIdPointer);
            bw.Write(LineIdPointer);

            //节点信息
            bw.Write(NodeCount);
            foreach (var node in Nodes.Values)
                bw.Write(node);

            //线信息
            bw.Write(LineCount);
            foreach (var line in Lines.Values)
                bw.Write(line);

            //尾信息
            bw.Write(EndFlag);
            return true;
        }

        public override WorkPage LoadFromBytes(BinaryReader br)
        {
            int iv;
            if (br.ReadByte() != StartFlag)
                throw new Exception("Unexpected start");
            m_name = br.ReadString();
            iv = br.ReadInt32();
            PaperSize = new Size(iv, br.ReadInt32());

            //idptr
            NodeIdPointer = br.ReadInt32();
            LineIdPointer = br.ReadInt32();

            //节点信息
            iv = br.ReadInt32();
            Nodes = new Dictionary<int, FCNode>(iv);
            for (int i = 0; i < iv; i++)
            {
                var n = br.ReadFCNode();
                Nodes.Add(n.Id, n);
            }
            iv = br.ReadInt32();
            Lines = new Dictionary<int, FCLine>(iv);
            for (int i = 0; i < iv; i++)
            {
                var n = br.ReadFCLine();
                Lines.Add(n.Id, n);
            }
            /*
            * recored
            * */
            if (br.ReadByte() != EndFlag)
                throw new Exception("Unexpected end");
            return this;
        }

        protected override void _OnChangeName(string from, string to)
        {

        }
    }
}
